home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / sprite.X11R3 / hdr / cgfour.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-03  |  26.1 KB  |  1,180 lines

  1. #ifndef lint
  2. static char sccsid[] = "@(#)cgfour.c 1.1 87/12/21 SMI";
  3. #endif
  4.  
  5. /*
  6.  * Copyright 1986 by Sun Microsystems, Inc.
  7.  */
  8.  
  9. /*
  10.  * Color frame buffer with overlay plane (cg4) driver
  11.  */
  12.  
  13. #include "cgfour.h"
  14. #include "win.h"
  15.  
  16. #include "../h/param.h"
  17. #include "../h/time.h"
  18. #include "../h/buf.h"
  19. #include "../h/errno.h"
  20. #include "../h/ioctl.h"
  21. #include "../h/map.h"
  22. #include "../h/proc.h"
  23. #include "../h/user.h"
  24. #include "../h/vmmac.h"
  25.  
  26. #include "../sun/fbio.h"
  27.  
  28. #include "../sundev/mbvar.h"
  29. #include "../sundev/cg4reg.h"
  30. #include "../sundev/p4reg.h"
  31.  
  32. #include "../machine/eeprom.h"
  33. #include "../machine/enable.h"
  34. #include "../machine/mmu.h"
  35. #include "../machine/pte.h"
  36.  
  37. #include "../mon/sunromvec.h"
  38.  
  39. #include "../pixrect/pixrect.h"
  40. #include "../pixrect/pr_impl_util.h"
  41. #include "../pixrect/pr_util.h"
  42. #include "../pixrect/pr_planegroups.h"
  43. #include "../pixrect/cg4var.h"
  44.  
  45. /* system enable register */
  46. extern u_char enablereg;
  47.  
  48. /* colormap update firsthalf, toolate error counts */
  49. int cg4_firsthalf = 0;
  50. int cg4_toolate = 0;
  51.  
  52. /* driver per-unit data */
  53. struct cg4_softc {
  54.     short        type;        /* type code (0 = A, 1 = B) */
  55.     short        flags;        /* internal flags */
  56. #define    CG4_UPDATE_PENDING    1    /* colormap update in progress */
  57. #undef    CG4_OVERLAY_CMAP        /* also defined in cg4var.h (urk) */
  58. #define    CG4_OVERLAY_CMAP    2    /* has overlay colormap */
  59. #define    CG4_OWNER_WANTS_COLOR    4    /* auto-init should display color */
  60.     caddr_t        fb[CG4_NFBS];    /* pointers to frame buffer sections */
  61.     int        w, h;        /* resolution */
  62.     int        size;        /* total size of frame buffer */
  63.     int        bw2size;    /* total size of overlay plane */
  64.     struct proc    *owner;        /* owner of the frame buffer */
  65.     struct fbgattr    gattr;        /* current attributes */
  66.     u_long        *p4reg;        /* pointer to P4 register */
  67.  
  68.     /* color map stuff */
  69.     union cg4_cmap {
  70. #ifdef CG4A
  71.         struct cg4a_cmap a;
  72. #endif CG4A
  73.         struct cg4b_cmap b;
  74.     } *cmap;            /* pointer to hardware colormap */
  75.     union {                /* shadow overlay color map */
  76.         u_char    omap_char[3][2];
  77.     } omap_image;
  78. #define    omap_red    omap_image.omap_char[0]
  79. #define    omap_green    omap_image.omap_char[1]
  80. #define    omap_blue    omap_image.omap_char[2]
  81. #define    omap_rgb    omap_image.omap_char[0]
  82.     u_short        cmap_index;    /* colormap update index */
  83.     u_short        cmap_count;    /* colormap update count */
  84.     union {                /* shadow color map */
  85.         u_long    cmap_long[CG4_CMAP_ENTRIES * 3 / sizeof(u_long)];
  86.         u_char    cmap_char[3][CG4_CMAP_ENTRIES];
  87.     } cmap_image;
  88. #define    cmap_red    cmap_image.cmap_char[0]
  89. #define    cmap_green    cmap_image.cmap_char[1]
  90. #define    cmap_blue    cmap_image.cmap_char[2]
  91. #define    cmap_rgb    cmap_image.cmap_char[0]
  92.  
  93. #if NWIN > 0
  94.     Pixrect        pr;
  95.     struct cg4_data    cgd;
  96. #endif NWIN > 0
  97. } cg4_softc[NCGFOUR];
  98.  
  99. /* probe size -- enough for the P4 register + colormap/status register */
  100. #define    CG4_PROBESIZE    (NBPG + sizeof *cg4_softc[0].cmap)
  101.  
  102. /* Mainbus device data */
  103. int cgfourprobe(), cgfourattach(), cgfourpoll();
  104. struct  mb_device *cgfourinfo[NCGFOUR];
  105. struct  mb_driver cgfourdriver = {
  106.     cgfourprobe, 0, cgfourattach, 0, 0, cgfourpoll,
  107.     CG4_PROBESIZE, "cgfour", cgfourinfo, 0, 0, 0, 0
  108. };
  109.  
  110. /* default structure for FBIOGTYPE ioctl */
  111. static struct fbtype cg4typedefault =  {
  112. /*    type           h  w  depth cms size */
  113.     FBTYPE_SUN2BW, 0, 0, 1,    2,   0
  114. };
  115.  
  116. /* default structure for FBIOGATTR ioctl */
  117. static struct fbgattr cg4attrdefault =  {
  118. /*    real_type         owner */
  119.     FBTYPE_SUN4COLOR, 0,
  120. /* fbtype: type             h  w  depth cms  size */
  121.     { FBTYPE_SUN4COLOR, 0, 0, 8,    256,  0 }, 
  122. /* fbsattr: flags           emu_type       dev_specific */
  123.     { FB_ATTR_AUTOINIT, FBTYPE_SUN2BW, { 0 } },
  124. /*        emu_types */
  125.     { FBTYPE_SUN4COLOR, FBTYPE_SUN2BW, -1, -1}
  126. };
  127.  
  128. /* frame buffer description table */
  129. static struct cg4_fbdesc {
  130.     short    depth;            /* depth, bits */
  131.     short    group;            /* plane group */
  132.     int    allplanes;        /* initial plane mask */
  133. } cg4_fbdesc[CG4_NFBS + 1] = {
  134.     { 1, PIXPG_OVERLAY,          0 },
  135.     { 1, PIXPG_OVERLAY_ENABLE,      0 },
  136.     { 8, PIXPG_8BIT_COLOR,        255 }
  137. };
  138. #define    CG4_FBINDEX_OVERLAY    0
  139. #define    CG4_FBINDEX_ENABLE    1
  140. #define    CG4_FBINDEX_COLOR    2
  141.  
  142. /* initial active frame buffer */
  143. #ifndef    CG4_INITFB
  144. #define    CG4_INITFB    CG4_FBINDEX_COLOR
  145. #endif
  146.  
  147. /* macros */
  148. typedef IF68000(u_long, u_char) CMAP_T;
  149.  
  150. #define ITEMSIN(array)  (sizeof (array) / sizeof (array)[0])
  151. #define    ENDOF(array)    ((array) + ITEMSIN(array))
  152.  
  153. /* enable/disable interrupt */
  154. #define    cg4_int_enable(softc)    _STMT( \
  155.     if ((softc)->p4reg) \
  156.         *(softc)->p4reg |= P4_REG_INTEN | P4_REG_INTCLR; \
  157.     setintrenable(1);)
  158.  
  159. #define    cg4_int_disable(softc)    _STMT( \
  160.     setintrenable(0); \
  161.     if ((softc)->p4reg) \
  162.         *(softc)->p4reg &= ~P4_REG_INTEN;)
  163.  
  164. /* check if color map update is pending */
  165. #define    cgfour_update_pending(softc)    ((softc)->flags & CG4_UPDATE_PENDING)
  166.  
  167. /* 
  168.  * Compute color map update parameters: starting index and count.
  169.  * If count is already nonzero, adjust values as necessary.
  170.  * Zero count argument indicates overlay color map update desired
  171.  * (may cause bus error if hardware doesn't have overlay color map).
  172.  */
  173. #ifdef lint
  174. #define    cgfour_update_cmap(softc, index, count)    \
  175.     (softc)->cmap_index = (index) + (count);
  176. #else lint
  177. #define    cgfour_update_cmap(softc, index, count)    \
  178.     if (count) \
  179.         if ((softc)->cmap_count) { \
  180.             if ((index) + (count) > \
  181.                 (softc)->cmap_count += (softc)->cmap_index) \
  182.                 (softc)->cmap_count = (index) + (count); \
  183.             if ((index) < (softc)->cmap_index) \
  184.                 (softc)->cmap_index = (index); \
  185.             (softc)->cmap_count -= (softc)->cmap_index; \
  186.         } \
  187.         else { \
  188.             (softc)->cmap_index = (index); \
  189.             (softc)->cmap_count = (count); \
  190.             (softc)->flags |= CG4_UPDATE_PENDING; \
  191.         } \
  192.     else \
  193.         (softc)->flags |= CG4_UPDATE_PENDING
  194. #endif lint
  195.  
  196. /* forward references */
  197. static void cgfour_set_enable_plane();
  198. static void cgfour_reset_cmap();
  199. static void cgfour_cmap_bcopy();
  200. static void cgfour_reset_b();
  201. static void cgfourintr_a();
  202. static void cgfourintr_b();
  203.  
  204.  
  205. #if NWIN > 0
  206.  
  207. /* SunWindows specific stuff */
  208.  
  209. /* kernel pixrect ops vector */
  210. struct pixrectops cg4_ops = {
  211.     mem_rop,
  212.     cg4_putcolormap,
  213.     cg4_putattributes
  214. };
  215.  
  216. cg4_putcolormap(pr, index, count, red, green, blue)
  217.     Pixrect *pr;
  218.     int index, count;
  219.     unsigned char *red, *green, *blue;
  220. {
  221.     register struct cg4_softc *softc = &cg4_softc[cg4_d(pr)->fd];
  222.     register u_int rindex = (u_int) index;
  223.     register u_int rcount = (u_int) count;
  224.     register u_char *map;
  225.     register u_int entries;
  226.  
  227.     switch (softc->cgd.active) {
  228.     case CG4_FBINDEX_COLOR:
  229.         map = softc->cmap_rgb;
  230.         entries = CG4_CMAP_ENTRIES;
  231.         break;
  232.  
  233.     case CG4_FBINDEX_OVERLAY:
  234.         if (softc->flags & CG4_OVERLAY_CMAP) {
  235.             map = softc->omap_rgb;
  236.             entries = 2;
  237.             break;
  238.         }
  239.         /* fall through */
  240.  
  241.     default:
  242.         if (mem_putcolormap(&softc->pr, index, count, 
  243.             red, green, blue))
  244.             return PIX_ERR;
  245.  
  246.         softc->cgd.fb[softc->cgd.active].mprp.mpr.md_flags =
  247.             softc->cgd.mprp.mpr.md_flags;
  248.  
  249.         return 0;
  250.     }
  251.  
  252.     /* check arguments */
  253.     if (rindex >= entries || 
  254.         rindex + rcount > entries) 
  255.         return PIX_ERR;
  256.  
  257.     if (rcount == 0)
  258.         return 0;
  259.  
  260.     /* lock out updates of the hardware colormap */
  261.     if (cgfour_update_pending(softc))
  262.         cg4_int_disable(softc);
  263.  
  264.     switch (softc->type) {
  265.     case 0:
  266. #ifdef CG4A
  267.         map += rindex;
  268.         bcopy((caddr_t) red,   (caddr_t) map, rcount);
  269.         map += entries;
  270.         bcopy((caddr_t) green, (caddr_t) map, rcount);
  271.         map += entries;
  272.         bcopy((caddr_t) blue,  (caddr_t) map, rcount);
  273.         break;
  274.     case 1:
  275. #endif CG4A
  276.         map += rindex * 3;
  277.         cgfour_cmap_bcopy(red,   map++, rcount);
  278.         cgfour_cmap_bcopy(green, map++, rcount);
  279.         cgfour_cmap_bcopy(blue,  map,   rcount);
  280.         break;
  281.     }
  282.  
  283.     /* overlay colormap update */
  284.     if (entries <= 2)
  285.         rcount = 0;
  286.  
  287.     cgfour_update_cmap(softc, rindex, rcount);
  288.  
  289.     /* enable interrupt so we can load the hardware colormap */
  290.     cg4_int_enable(softc);
  291.  
  292.     return 0;
  293. }
  294.  
  295. #endif    NWIN > 0
  296.  
  297. /*
  298.  * Determine if a cgfour exists at the given address.
  299.  */
  300. /*ARGSUSED*/
  301. cgfourprobe(reg, unit)
  302.     caddr_t reg;
  303.     int unit;
  304. {
  305.     static struct cg4_ptab {
  306.         int    cmap_addr;        /* color map address */
  307.         int    fb_addr[CG4_NFBS];    /* frame buffer addresses */
  308.     } cg4_ptab[CG4_NTYPES] = {
  309. #ifdef CG4A
  310.     {    CG4A_PGT_CMAP | btop(CG4A_ADDR_CMAP), {
  311.           CG4A_PGT_FB | btop(CG4A_ADDR_OVERLAY), 
  312.         CG4A_PGT_FB | btop(CG4A_ADDR_ENABLE), 
  313.         CG4A_PGT_FB | btop(CG4A_ADDR_COLOR)
  314.     } },
  315. #endif CG4A
  316.     {    CG4B_PGT_CMAP | btop(CG4B_ADDR_CMAP), {
  317.         CG4B_PGT_FB | btop(CG4B_ADDR_OVERLAY), 
  318.         CG4B_PGT_FB | btop(CG4B_ADDR_ENABLE), 
  319.         CG4B_PGT_FB | btop(CG4B_ADDR_COLOR) 
  320.     } } };
  321.  
  322.     register struct cg4_softc *softc = &cg4_softc[unit];
  323.     register struct cg4_ptab *ptab = cg4_ptab;
  324.     int pages1, pages8;
  325.     long kmx, rmalloc();
  326.  
  327.     /* make sure this unit is not in use */
  328.     if (softc->cmap)
  329.         return 0;
  330.  
  331.     /* probe the colormap and determine the cg4 type */
  332.     {
  333.         register union cg4_cmap *cmap = (union cg4_cmap *) reg + NBPG;
  334.  
  335. #ifdef CG4A
  336.         softc->type = 0;
  337. #else  CG4A
  338.         softc->type = 1;
  339. #endif CG4A
  340.  
  341.         while (1) {
  342.             fbmapin((caddr_t) cmap, ptab->cmap_addr, sizeof *cmap);
  343.  
  344.             if (peekc((char *) cmap) != -1) 
  345.                 break;
  346.  
  347.             if (++ptab >= ENDOF(cg4_ptab))
  348.                 return 0;
  349.  
  350.             softc->type++;
  351.         }
  352.  
  353.         softc->cmap = cmap;
  354.     }
  355.  
  356.     /* 
  357.      * Determine frame buffer resolution:
  358.      *
  359.      * 1. If this is a P4 frame buffer, use the P4 type code.
  360.      * 2. Otherwise, assume it's a 3/110.  Use the EEPROM size code
  361.      *    to guess whether it's 1152 x 900 or 1024 x 1024.
  362.      */
  363.     {
  364.         int id;
  365.  
  366.         if ((id = p4probe(reg, &softc->w, &softc->h)) >= 0) {
  367.             if (id != P4_ID_COLOR8P1)
  368.                 return 0;
  369.  
  370.             softc->p4reg = (u_long *) reg;
  371.         }
  372.         else {
  373.             softc->p4reg = 0;
  374.  
  375.             softc->w = 1152;
  376.             softc->h = 900;
  377.  
  378.             if (EEPROM->ee_diag.eed_scrsize == EED_SCR_1024X1024) {
  379.                 softc->w = 1024;
  380.                 softc->h = 1024;
  381.             }
  382.         }
  383.  
  384.         pages1 = btoc(mpr_linebytes(softc->w, 1) * softc->h);
  385.         pages8 = btoc(mpr_linebytes(softc->w, 8) * softc->h);
  386.     }
  387.  
  388.     softc->size = 0;
  389.     softc->bw2size = ctob(pages1);
  390.  
  391.     /* map frame buffer sections */
  392.     {
  393.         register caddr_t fbaddr;
  394.         register int fb;
  395.  
  396.         /* allocate kernel space for all sections */
  397.         if ((kmx = rmalloc(kernelmap, 
  398.             (long) (pages1 + pages1 + pages8))) == 
  399.             0L) {
  400.             printf("cgfourprobe: out of kernelmap\n");
  401.             fbmapout((caddr_t) softc->cmap, sizeof *softc->cmap);
  402.             return 0;
  403.         }
  404.  
  405.         /* compute virtual addr. of first section */
  406.         fbaddr = (caddr_t) kmxtob(kmx);
  407.  
  408.         /* map each frame buffer section */
  409.         for (fb = 0; fb < CG4_NFBS; fb++) {
  410.             register int pages;
  411.  
  412.             pages = cg4_fbdesc[fb].depth == 1 ? pages1 : pages8;
  413.  
  414.             fbmapin(fbaddr, ptab->fb_addr[fb], ctob(pages));
  415.  
  416.             softc->fb[fb] = fbaddr;
  417.             softc->size += ctob(pages);
  418.  
  419.             if (peekc((char *) fbaddr) != -1) {
  420.                 fbaddr += ctob(pages);
  421.                 continue;
  422.             }
  423.  
  424.             /* this section missing, map out everything */
  425.             fbmapout((caddr_t) softc->cmap, sizeof *softc->cmap);
  426.             fbmapout(softc->fb[0], softc->size);
  427.  
  428.             (void) rmfree(kernelmap, 
  429.                 (long) (pages1 + pages1 + pages8), kmx);
  430.  
  431.             return 0;
  432.         }
  433.     }
  434.  
  435.     /* probe succeeded */
  436.     return CG4_PROBESIZE;
  437. }
  438.  
  439.  
  440. cgfourattach(md)
  441.     register struct mb_device *md;
  442. {
  443.     register struct cg4_softc *softc = &cg4_softc[md->md_unit];
  444.  
  445.     softc->flags = 0;
  446.     softc->owner = NULL;
  447.  
  448.      softc->gattr = cg4attrdefault;
  449.     softc->gattr.fbtype.fb_height = softc->h;
  450.     softc->gattr.fbtype.fb_width =  softc->w;
  451.     softc->gattr.fbtype.fb_size = softc->size;
  452.  
  453.     /* 
  454.      * Initialize hardware colormap and software colormap images.
  455.      * It might make sense to read the hardware colormap here. 
  456.      */
  457.     if (softc->type) {
  458.         cgfour_reset_b(softc);
  459.         softc->flags = CG4_OVERLAY_CMAP;
  460.     }
  461.     cgfour_reset_cmap(softc, softc->omap_rgb, 2);
  462.     cgfour_reset_cmap(softc, softc->cmap_rgb, CG4_CMAP_ENTRIES);
  463.     cgfour_update_cmap(softc, 0, CG4_CMAP_ENTRIES);
  464. }
  465.  
  466. cgfouropen(dev, flag)
  467.     dev_t dev;
  468.     int flag;
  469. {
  470.     return fbopen(dev, flag, NCGFOUR, cgfourinfo);
  471. }
  472.  
  473. /*ARGSUSED*/
  474. cgfourclose(dev, flag)
  475.     dev_t dev;
  476.     int flag;
  477. {
  478.     register struct cg4_softc *softc = &cg4_softc[minor(dev)];
  479.  
  480.     softc->flags &= CG4_UPDATE_PENDING | CG4_OVERLAY_CMAP;
  481.     softc->owner = NULL;
  482.  
  483.      softc->gattr = cg4attrdefault;
  484.     softc->gattr.fbtype.fb_height = softc->h;
  485.     softc->gattr.fbtype.fb_width =  softc->w;
  486.     softc->gattr.fbtype.fb_size = softc->size;
  487.  
  488.     /* re-initialize overlay colormap (this is a hack!) */
  489.     if (softc->flags & CG4_OVERLAY_CMAP) {
  490.         if (cgfour_update_pending(softc))
  491.             cg4_int_disable(softc);
  492.         cgfour_reset_cmap(softc, softc->omap_rgb, 2);
  493.         cgfour_update_cmap(softc, 0, 0);
  494.         cg4_int_enable(softc);
  495.     }
  496. }
  497.  
  498. /*ARGSUSED*/
  499. cgfourmmap(dev, off, prot)
  500.     dev_t dev;
  501.     off_t off;
  502.     int prot;
  503. {
  504.     register struct cg4_softc *softc = &cg4_softc[minor(dev)];
  505.  
  506.     /* 
  507.      * Initialize overlay enable plane if necessary.
  508.      *
  509.      * If the owner wants color (as inferred from its use of the
  510.      * FBIOGATTR ioctl), set to display color planes.
  511.      * (This is a hack.)
  512.      *
  513.      * Note this will work for a non-owner process as long as
  514.      * the autoinit bit is set.
  515.      */
  516.     if (softc->gattr.sattr.flags & FB_ATTR_AUTOINIT) {
  517.         cgfour_set_enable_plane(softc->fb[CG4_FBINDEX_ENABLE], 
  518.             softc->w, softc->h,
  519.             softc->flags & CG4_OWNER_WANTS_COLOR ? 0 : 1);
  520.  
  521.         softc->gattr.sattr.flags &= ~FB_ATTR_AUTOINIT;
  522.     }
  523.  
  524.     if ((u_int) off >= softc->size)
  525.         return -1;
  526.  
  527.     return fbgetpage(softc->fb[0] + off);
  528. }
  529.  
  530. /*ARGSUSED*/
  531. cgfourioctl(dev, cmd, data, flag)
  532.     dev_t dev;
  533.     int cmd;
  534.     caddr_t data;
  535.     int flag;
  536. {
  537.     register struct cg4_softc *softc = &cg4_softc[minor(dev)];
  538.     static u_char cmapbuf[CG4_CMAP_ENTRIES];
  539.  
  540.     switch (cmd) {
  541.  
  542.     case FBIOPUTCMAP: 
  543.     case FBIOGETCMAP: {
  544.         register struct fbcmap *cmap = (struct fbcmap *) data;
  545.         register u_int index = (u_int) cmap->index;
  546.         register u_int count = (u_int) cmap->count;
  547.         register u_char *map;
  548.         register u_int entries;
  549.  
  550.         switch (PIX_ATTRGROUP(index)) {
  551.         case 0:
  552.         case PIXPG_8BIT_COLOR:
  553.             map = softc->cmap_rgb;
  554.             entries = CG4_CMAP_ENTRIES;
  555.             break;
  556.  
  557.         case PIXPG_OVERLAY:
  558.             if (softc->flags & CG4_OVERLAY_CMAP) {
  559.                 map = softc->omap_rgb;
  560.                 entries = 2;
  561.                 break;
  562.             }
  563.             /* fall through */
  564.  
  565.         default:
  566.             return EINVAL;
  567.         }
  568.  
  569.         if ((index &= PIX_ALL_PLANES) >= entries || 
  570.             index + count > entries)
  571.             return EINVAL;
  572.  
  573.         if (count == 0)
  574.             return 0;
  575.  
  576.         if (cmd == FBIOPUTCMAP) { 
  577.             register int error;
  578.  
  579.             if (cgfour_update_pending(softc))
  580.                 cg4_int_disable(softc);
  581.  
  582.             switch (softc->type) {
  583. #ifdef CG4A
  584.             case 0:
  585.                 error = copyin((caddr_t) cmap->red, 
  586.                     (caddr_t) (map += index), count) ||
  587.                     copyin((caddr_t) cmap->green, 
  588.                     (caddr_t) (map += entries), count) ||
  589.                     copyin((caddr_t) cmap->blue, 
  590.                     (caddr_t) (map += entries), count);
  591.                 break;
  592. #endif CG4A
  593.             case 1:
  594.                 map += index * 3;
  595.  
  596.                 if (error = copyin((caddr_t) cmap->red, 
  597.                     (caddr_t) cmapbuf, count))
  598.                     break;
  599.                 cgfour_cmap_bcopy(cmapbuf, map++, count);
  600.  
  601.                 if (error = copyin((caddr_t) cmap->green, 
  602.                     (caddr_t) cmapbuf, count))
  603.                     break;
  604.                 cgfour_cmap_bcopy(cmapbuf, map++, count);
  605.  
  606.                 if (error = copyin((caddr_t) cmap->blue, 
  607.                     (caddr_t) cmapbuf, count))
  608.                     break;
  609.                 cgfour_cmap_bcopy(cmapbuf, map, count);
  610.  
  611.                 break;
  612.             }
  613.  
  614.             if (error) {
  615.                 if (cgfour_update_pending(softc)) 
  616.                     cg4_int_enable(softc);
  617.                 return EFAULT;
  618.             }
  619.  
  620.             /* overlay colormap update */
  621.             if (entries <= 2)
  622.                 count = 0;
  623.  
  624.             cgfour_update_cmap(softc, index, count);
  625.             cg4_int_enable(softc);
  626.         }
  627.         else {
  628.             /* FBIOGETCMAP */
  629.             switch (softc->type) {
  630. #ifdef CG4A
  631.             case 0:
  632.                 if (copyout((caddr_t) (map += index),
  633.                     (caddr_t) cmap->red, count) ||
  634.                     copyout((caddr_t) (map += entries),
  635.                     (caddr_t) cmap->green, count) ||
  636.                     copyout((caddr_t) (map += entries),
  637.                     (caddr_t) cmap->blue, count))
  638.                     return EFAULT;
  639.  
  640.                 break;
  641. #endif CG4A
  642.             case 1: 
  643.                 map += index * 3;
  644.                 cgfour_cmap_bcopy(cmapbuf, map++, -count);
  645.                 if (copyout((caddr_t) cmapbuf,
  646.                     (caddr_t) cmap->red, count))
  647.                     return EFAULT;
  648.  
  649.                 cgfour_cmap_bcopy(cmapbuf, map++, -count);
  650.                 if (copyout((caddr_t) cmapbuf,
  651.                     (caddr_t) cmap->green, count))
  652.                     return EFAULT;
  653.  
  654.                 cgfour_cmap_bcopy(cmapbuf, map, -count);
  655.                 if (copyout((caddr_t) cmapbuf,
  656.                     (caddr_t) cmap->blue, count))
  657.                     return EFAULT;
  658.  
  659.                 break;
  660.             }
  661.         }
  662.     }
  663.     break;
  664.  
  665.     case FBIOSATTR: {
  666.         register struct fbsattr *sattr = (struct fbsattr *) data;
  667.  
  668. #ifdef ONLY_OWNER_CAN_SATTR
  669.         /* this can only happen for the owner */
  670.         if (softc->owner != u.u_procp)
  671.             return ENOTTY;
  672. #endif ONLY_OWNER_CAN_SATTR
  673.  
  674.         softc->gattr.sattr.flags = sattr->flags;
  675.  
  676.         if (sattr->emu_type != -1)
  677.             softc->gattr.sattr.emu_type = sattr->emu_type;
  678.  
  679.         if (sattr->flags & FB_ATTR_DEVSPECIFIC) {
  680.             bcopy((char *) sattr->dev_specific,
  681.                 (char *) softc->gattr.sattr.dev_specific,
  682.                 sizeof sattr->dev_specific);
  683.  
  684.             if (softc->gattr.sattr.dev_specific
  685.                 [FB_ATTR_CG4_SETOWNER_CMD] == 1) {
  686.                 struct proc *pfind();
  687.                 register struct proc *newowner = 0;
  688.  
  689.                 if (softc->gattr.sattr.dev_specific
  690.                     [FB_ATTR_CG4_SETOWNER_PID] > 0 &&
  691.                     (newowner = pfind(
  692.                     softc->gattr.sattr.dev_specific
  693.                         [FB_ATTR_CG4_SETOWNER_PID]))) {
  694.                     softc->owner = newowner;
  695.                     softc->gattr.owner = newowner->p_pid;
  696.                 }
  697.  
  698.                 softc->gattr.sattr.dev_specific
  699.                     [FB_ATTR_CG4_SETOWNER_CMD] = 0;
  700.                 softc->gattr.sattr.dev_specific
  701.                     [FB_ATTR_CG4_SETOWNER_PID] = 0;
  702.  
  703.                 if (!newowner)
  704.                     return ESRCH;
  705.             }
  706.         }
  707.     }
  708.     break;
  709.  
  710.     case FBIOGATTR: {
  711.         register struct fbgattr *gattr = (struct fbgattr *) data;
  712.  
  713.         /* set owner if not owned or previous owner is dead */
  714.         if (softc->owner == NULL || 
  715.             softc->owner->p_stat == NULL ||
  716.             softc->owner->p_pid != softc->gattr.owner) {
  717.  
  718.             softc->owner = u.u_procp;
  719.             softc->gattr.owner = u.u_procp->p_pid;
  720.             softc->gattr.sattr.flags |= FB_ATTR_AUTOINIT;
  721.         }
  722.  
  723.         *gattr = softc->gattr;
  724.  
  725.         if (u.u_procp == softc->owner) {
  726.             gattr->owner = 0;
  727.             softc->flags |= CG4_OWNER_WANTS_COLOR;
  728.         }
  729.     }
  730.     break;
  731.  
  732.     case FBIOGTYPE: {
  733.         register struct fbtype *fb = (struct fbtype *) data;
  734.  
  735.         /* set owner if not owned or previous owner is dead */
  736.         if (softc->owner == NULL || 
  737.             softc->owner->p_stat == NULL || 
  738.             softc->owner->p_pid != softc->gattr.owner) {
  739.  
  740.             softc->owner = u.u_procp;
  741.             softc->gattr.owner = u.u_procp->p_pid;
  742.             softc->gattr.sattr.flags |= FB_ATTR_AUTOINIT;
  743.         }
  744.  
  745.         switch(softc->gattr.sattr.emu_type) {
  746.         case FBTYPE_SUN2BW:
  747.             *fb = cg4typedefault;
  748.             fb->fb_height = softc->h;
  749.             fb->fb_width  = softc->w;
  750.             fb->fb_size = softc->bw2size;
  751.             break;
  752.  
  753.         case FBTYPE_SUN4COLOR:
  754.         default:
  755.             *fb = softc->gattr.fbtype;
  756.             break;
  757.         }
  758.     }
  759.     break;
  760.  
  761. #if NWIN > 0
  762.  
  763.     case FBIOGPIXRECT: {
  764.         struct fbpixrect *fbpr = (struct fbpixrect *) data;
  765.         register struct cg4fb *fbp;
  766.         register struct cg4_fbdesc *descp;
  767.         register int i;
  768.  
  769.         /* "Allocate" pixrect and private data */
  770.         fbpr->fbpr_pixrect = &softc->pr;
  771.         softc->pr.pr_data = (caddr_t) &softc->cgd;
  772.  
  773.         /* initialize pixrect */
  774.         softc->pr.pr_ops = &cg4_ops;
  775.         softc->pr.pr_size.x = softc->w;
  776.         softc->pr.pr_size.y = softc->h;
  777.  
  778.         /* initialize private data */
  779.         softc->cgd.flags = 0;
  780.         softc->cgd.planes = 0;
  781.         softc->cgd.fd = minor(dev);
  782.  
  783.         for (fbp = softc->cgd.fb, descp = cg4_fbdesc, i = 0; 
  784.             i < CG4_NFBS; fbp++, descp++, i++) {
  785.             fbp->group = descp->group;
  786.             fbp->depth = descp->depth;
  787.             fbp->mprp.mpr.md_linebytes = 
  788.                 mpr_linebytes(softc->w, descp->depth);
  789.             fbp->mprp.mpr.md_image = (short *) softc->fb[i];
  790.             fbp->mprp.mpr.md_offset.x = 0;
  791.             fbp->mprp.mpr.md_offset.y = 0;
  792.             fbp->mprp.mpr.md_primary = 0;
  793.             fbp->mprp.mpr.md_flags = descp->allplanes != 0
  794.                 ? MP_DISPLAY | MP_PLANEMASK
  795.                 : MP_DISPLAY;
  796.             fbp->mprp.planes = descp->allplanes;
  797.         }
  798.  
  799.         /* set up pixrect initial state */
  800.         {
  801.             int initplanes = 
  802.                 PIX_GROUP(cg4_fbdesc[CG4_INITFB].group) |
  803.                 cg4_fbdesc[CG4_INITFB].allplanes;
  804.  
  805.             (void) cg4_putattributes(&softc->pr, &initplanes);
  806.         }
  807.  
  808.         /* enable video */
  809.         if (softc->p4reg)
  810.             *softc->p4reg |= P4_REG_VIDEO;
  811.         else
  812.             setvideoenable(1);
  813.     }
  814.     break;
  815.  
  816. #endif NWIN > 0
  817.  
  818.     case FBIOSVIDEO: {
  819.         register int on = * (int *) data & FBVIDEO_ON;
  820.  
  821.         if (softc->p4reg)
  822.             *softc->p4reg = *softc->p4reg & 
  823.                 ~(P4_REG_INTCLR | P4_REG_VIDEO) |
  824.                 (on ? P4_REG_VIDEO : 0);
  825.         else
  826.             setvideoenable((u_int) on);
  827.     }
  828.     break;
  829.  
  830.     /* get video flags */
  831.     case FBIOGVIDEO:
  832.         * (int *) data = 
  833.             (softc->p4reg ?
  834.                 *softc->p4reg & P4_REG_VIDEO :
  835.                 enablereg & ENA_VIDEO) ?
  836.                 FBVIDEO_ON : FBVIDEO_OFF;
  837.         break;
  838.  
  839.     default:
  840.         return ENOTTY;
  841.  
  842.     } /* switch(cmd) */
  843.  
  844.     return 0;
  845. }
  846.  
  847. cgfourpoll()
  848. {
  849.     register int serviced = 0;
  850.     register struct cg4_softc *softc;
  851.  
  852.     /* 
  853.      * Look for any frame buffers that were expecting an interrupt.
  854.      * For P4 frame buffers, check the interrupt status bit too.
  855.      */
  856.     for (softc = cg4_softc; softc < ENDOF(cg4_softc); softc++)
  857.         if (cgfour_update_pending(softc)) {
  858.             switch (softc->type) {
  859. #ifdef CG4A
  860.             case 0:
  861.                 cgfourintr_a(softc); 
  862.                 serviced++; 
  863.                 break;
  864. #endif CG4A
  865.             case 1:
  866.                 if (!softc->p4reg ||
  867.                     *softc->p4reg & P4_REG_INT)
  868.                     cgfourintr_b(softc); 
  869.                     serviced++;
  870.                 }
  871.                 break;
  872.             }
  873.         /* catch stray P4 interrupts */
  874.         else if (softc->p4reg && 
  875.             *softc->p4reg & P4_REG_INT) {
  876.             cg4_int_disable(softc);
  877.             serviced++;
  878.         }
  879.  
  880.     return serviced;
  881. }
  882.  
  883. #ifdef CG4A
  884.  
  885. static void
  886. cgfourintr_a(softc) 
  887.     register struct cg4_softc *softc;
  888. {
  889.     register struct cg4a_cmap *cmap = &softc->cmap->a;
  890.  
  891.     /* make sure we're in the first half of vertical blanking period */
  892.     if (cmap->status & CG4A_STATUS_FIRSTHALF) {
  893.         register LOOP_T count = softc->cmap_count;
  894.         register u_long *in  = &softc->cmap_image.cmap_long[0];
  895.         register CMAP_T *out = (CMAP_T *) cmap->red;
  896.  
  897.         /* loading most or all of colormap, use unrolled loop */
  898. #ifdef mc68000
  899.         if (count >= 160) {
  900.             count = CG4_CMAP_ENTRIES * 3 / sizeof *out / 8 - 1;
  901.  
  902.             PR_LOOPVP(count,
  903.                 *out++ = *in++;
  904.                 *out++ = *in++;
  905.                 *out++ = *in++;
  906.                 *out++ = *in++;
  907.                 *out++ = *in++;
  908.                 *out++ = *in++;
  909.                 *out++ = *in++;
  910.                 *out++ = *in++);
  911.         }
  912.         /* small to medium colormap load, use rolled loop */
  913.         else 
  914. #endif mc68000
  915.         {
  916.             register int index = softc->cmap_index;
  917.  
  918.             /* convert count to longs */
  919.             count = (count + (index & 3) + 3) >> 2;
  920.  
  921.             /* round index to long boundary */
  922.             index &= ~3;
  923.  
  924.             PTR_INCR(u_long *, in, index);
  925.             PTR_INCR(CMAP_T *, out, index);
  926.  
  927.             index = ((CG4_CMAP_ENTRIES >> 2) - count) << 2;
  928.             count--;
  929.  
  930.             PR_LOOPP(3 - 1,
  931.                 PR_LOOPP(count,
  932.                     IF68000(
  933.                         *out++ = *in++
  934.                         ,
  935.                         register u_long tmp;
  936.  
  937.                         tmp = *in++;
  938.                         *out++ = tmp >> 24;
  939.                         *out++ = tmp >> 16;
  940.                         *out++ = tmp >> 8;
  941.                         *out++ = tmp));
  942.                 PTR_INCR(u_long *, in, index);
  943.                 PTR_INCR(CMAP_T *, out, index));
  944.         }
  945.  
  946.         /* update toolate statistics */
  947.         if (cmap->status & CG4A_STATUS_TOOLATE)
  948.             cg4_toolate++;
  949.  
  950.         softc->cmap_count = 0;
  951.         softc->flags &= ~CG4_UPDATE_PENDING;
  952.         setintrenable(0);
  953.     }
  954.     /* missed first half of blanking, catch the next retrace */
  955.     else {
  956.         cg4_firsthalf++;
  957.         setintrenable(0);
  958.         setintrenable(1);
  959.     }
  960. }
  961. #endif CG4A
  962.  
  963. static void
  964. cgfourintr_b(softc) 
  965.     register struct cg4_softc *softc;
  966. {
  967.     register struct cg4b_cmap *cmap = &softc->cmap->b;
  968.  
  969.     /* load overlay color map */
  970.     {
  971.         register u_char *in = softc->omap_rgb;
  972.         register u_char *out = &cmap->omap;
  973.  
  974.         /* background color */
  975.         cmap->addr = 1;
  976.         *out = *in++;
  977.         *out = *in++;
  978.         *out = *in++;
  979.  
  980.         /* foreground color */
  981.         cmap->addr = 3;
  982.         *out = *in++;
  983.         *out = *in++;
  984.         *out = *in;
  985.     }
  986.  
  987.     /* load main color map */
  988.     {
  989.         register LOOP_T count = softc->cmap_count;
  990. #ifdef mc68000
  991.         register u_char *in = &softc->cmap_image.cmap_char[0][0];
  992. #else mc68000
  993.         register u_long *in = &softc->cmap_image.cmap_long[0];
  994.         register u_long tmp;
  995. #endif  mc68000
  996.  
  997.         {
  998.             register LOOP_T index = softc->cmap_index;
  999.  
  1000.             /* convert count to multiple of 12 bytes */
  1001.             count = ((count + (index & 3) + 3) >> 2) * 3;
  1002.  
  1003.             /* round index to 4 entry boundary */
  1004.             index &= ~3;
  1005.  
  1006.             cmap->addr = index;
  1007.             PTR_INCR(IF68000(u_char *, u_long *), in, index * 3);
  1008.         }
  1009.  
  1010.         {
  1011.             register u_char *out = &cmap->cmap;
  1012.  
  1013.             /* copy 4 bytes (4/3 RGB entries) per loop iteration */
  1014.             PR_LOOPV(count, IF68000(
  1015.                 *out = *in++;
  1016.                 *out = *in++;
  1017.                 *out = *in++;
  1018.                 *out = *in++;
  1019.                 ,
  1020.                 tmp = *in++;
  1021.                 *out = tmp >> 24;
  1022.                 *out = tmp >> 16;
  1023.                 *out = tmp >> 8;
  1024.                 *out = tmp;
  1025.                 ));
  1026.         }
  1027.     }
  1028.  
  1029.     softc->cmap_count = 0;
  1030.     softc->flags &= ~CG4_UPDATE_PENDING;
  1031.     cg4_int_disable(softc);
  1032. }
  1033.  
  1034. /* enable display of overlay plane or color planes */
  1035. static void
  1036. cgfour_set_enable_plane(image, w, h, overlay)
  1037.     caddr_t image;
  1038.     int w, h;
  1039.     int overlay;
  1040. {
  1041.     register u_long *lp = (u_long *) image, on, count;
  1042.  
  1043.     /* 1s enable the overlay plane, 0s enable the color planes */
  1044.     on = 0;
  1045.     if (overlay)
  1046.         on = ~on;
  1047.  
  1048.     /* compute number of 32-bit longs to be set */
  1049.     count = pr_product(mpr_linebytes(w, 1), h) >> 2;
  1050.  
  1051.     /* make sure count is a multiple of 8 */
  1052.     while ((count & 7) != 0) {
  1053.         *lp++ = on;
  1054.         count--;
  1055.     }
  1056.  
  1057.     PR_LOOP(count >> 3,
  1058.         *lp++ = on;
  1059.         *lp++ = on;
  1060.         *lp++ = on;
  1061.         *lp++ = on;
  1062.         *lp++ = on;
  1063.         *lp++ = on;
  1064.         *lp++ = on;
  1065.         *lp++ = on);
  1066. }
  1067.  
  1068. /*
  1069.  * Initialize a colormap: background = white, all others = black
  1070.  */
  1071. static void
  1072. cgfour_reset_cmap(softc, cmap, entries)
  1073.     register struct cg4_softc *softc;
  1074.     register u_char *cmap;
  1075.     register u_int entries;
  1076. {
  1077.     bzero((char *) cmap, entries * 3);
  1078.     switch (softc->type) {
  1079. #ifdef CG4A
  1080.     case 0:
  1081.         * cmap             = 255;
  1082.         *(cmap += entries) = 255;
  1083.         *(cmap += entries) = 255;
  1084.         break;
  1085. #endif CG4A
  1086.     case 1:
  1087.         *cmap++ = 255;
  1088.         *cmap++ = 255;
  1089.         *cmap   = 255;
  1090.         break;
  1091.     }
  1092. }
  1093.  
  1094. /*
  1095.  * Copy colormap entries between red, green, or blue array and
  1096.  * interspersed rgb array.
  1097.  *
  1098.  * count > 0 : copy count bytes from buf to rgb
  1099.  * count < 0 : copy -count bytes from rgb to buf
  1100.  */
  1101. static void
  1102. cgfour_cmap_bcopy(bufp, rgb, count)
  1103.     register u_char *bufp, *rgb;
  1104.     u_int count;
  1105. {
  1106.     register LOOP_T rcount = count;
  1107.  
  1108.     if (--rcount >= 0)
  1109.         PR_LOOPVP(rcount,
  1110.             *rgb = *bufp++;
  1111.             rgb += 3);
  1112.     else {
  1113.         rcount = -rcount - 2;
  1114.         PR_LOOPVP(rcount,
  1115.             *bufp++ = *rgb;
  1116.             rgb += 3);
  1117.     }
  1118. }
  1119.  
  1120. /* 
  1121.  * Initialize type B (Brooktree) color map chip.
  1122.  * This should be done by the boot PROM, but who knows?
  1123.  */
  1124. static void
  1125. cgfour_reset_b(softc)
  1126.     struct cg4_softc *softc;
  1127. {
  1128.     register struct cg4b_cmap *cmap = &softc->cmap->b;
  1129.     register u_char *p;
  1130.  
  1131.     /* control register initial values (addr, data) */
  1132.     static u_char ctrltab[4 * 2] = {
  1133.         /* read mask = all 1s */
  1134.         4, 0xff,
  1135.  
  1136.         /* blink mask = all 0s*/
  1137.         5, 0,
  1138.  
  1139.         /* 
  1140.          * command register
  1141.          *  CR7   0    4:1 multiplexing
  1142.          *  CR6   1    use color palette RAM
  1143.          *  CR5:4 11    blink divisor = 65536
  1144.          *  CR3:2 00    OL blink disabled
  1145.          *  CR1:0 11    OL display enabled
  1146.          */
  1147.         6, 0x73,
  1148.  
  1149.         /* test register = 0 */
  1150.         7, 0
  1151.     };
  1152.  
  1153.     /* overlay color map initial values */
  1154.     static u_char otab[12] = {
  1155.         /* OL color 0 (not used) = yellow */
  1156.         255, 255,   0,
  1157.  
  1158.         /* OL color 1 (overlay plane background) = white */
  1159.         255, 255, 255,
  1160.  
  1161.         /* OL color 2 (not used) = cyan */
  1162.           0, 255, 255,
  1163.  
  1164.         /* OL color 3 (overlay plane foreground) = black */
  1165.           0,   0,   0
  1166.     };
  1167.  
  1168.     /* load control registers */
  1169.     p = ctrltab;
  1170.     PR_LOOPP(ITEMSIN(ctrltab) / 2 - 1, 
  1171.         cmap->addr = *p++;
  1172.         cmap->ctrl = *p++);
  1173.  
  1174.     /* load overlay color map */
  1175.     cmap->addr = 0;
  1176.     p = otab;
  1177.     PR_LOOPP(ITEMSIN(otab) - 1, cmap->omap = *p++);
  1178. }
  1179.  
  1180.